﻿using System;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Services;
using Volo.Abp.DependencyInjection;
using YaAppoint.Appointments;
using YaAppoint.Appointments.CheckIn;
using YaAppoint.DapperRepositories;
using YaAppoint.ExamAppies;
using YaAppoint.RoslynCompiler;
using YaAppoint.TextTemplates;

namespace YaAppoint.OnlineServiceCache
{
    /// <summary>
    /// 在线服务缓存服务
    /// </summary>
    [RemoteService(isEnabled: false)]
    public class OnlineServiceCacheAppService(IDynamicCompilerAppService compilerAppService) : ApplicationService, IOnlineServiceCacheAppService, ITransientDependency
    {
        private readonly IDynamicCompilerAppService _compilerAppService = compilerAppService;
        /// <summary>
        /// 缓存中获取/添加OnlineService
        /// </summary>
        public async Task<OnlineService> GetOrAddOnlineService(TextTemplateDto dto)
        {
            OnlineService onlineService = null;
            // 检测在线服务类型
            switch (dto.Interface)
            {
                case "IApplyItemMapService":
                    onlineService = new OnlineService<IApplyItemMapService>();
                    onlineService.Type = OnlineServiceType.IApplyItemMapService;
                    break;

                case "IApplySearchConfigService":
                    onlineService = new OnlineService<IApplySearchConfigService>();
                    onlineService.Type = OnlineServiceType.IApplySearchConfigService;
                    break;

                case "ICheckInByApi":
                    onlineService = new OnlineService<ICheckInByApi>();
                    onlineService.Type = OnlineServiceType.ICheckInByApi;
                    break;

                case "IHisAndPacsCancelSevice":
                    onlineService = new OnlineService<IHisAndPacsCancelSevice>();
                    onlineService.Type = OnlineServiceType.IHisAndPacsCancelSevice;
                    break;

                case "IWriteBackToHisService":
                    onlineService = new OnlineService<IWriteBackToHisService>();
                    onlineService.Type = OnlineServiceType.IWriteBackToHisService;
                    break;

                default:
                    break;
            }
            if (onlineService == null)
            {
                throw new BusinessException(CustomErrorCodes.TemplateIsNotOnlineService);
            }

            onlineService.Name = dto.Name!;
            onlineService.TemplateId = dto.Id!.Value;
            onlineService.MD5 = _compilerAppService.GetCodeMD5(dto.Content);

            var cachedService = OnlineServiceCache.Get(dto.Id.Value);
            if (cachedService == null || cachedService.MD5 != onlineService.MD5)
            {
                if (cachedService != null)// 混存中存在，卸载对应的 AssemblyLoadContext
                {
                    cachedService.AssemblyLoadContext.Unload();
                }
                // 进行动态编译
                DynamicAssemblyLoadContext assemblyLoadContext = null;
                var instance = _compilerAppService.CreateInstanceWithDI(dto.Content!, dto.TypeName!, out assemblyLoadContext);
                if (instance == null)
                {
                    throw new Exception($"ID:{dto.Id}的在线服务，编译后未找到类型");
                }
                else
                {
                    onlineService.SetInstance(instance);
                }
                onlineService.AssemblyLoadContext = assemblyLoadContext;
                OnlineServiceCache.Set(dto.Id.Value, onlineService, null);
            }
            else
            {
                onlineService = cachedService;
            }
            return onlineService;
        }
    }
}
